package com.itheima.security;

import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.SysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.*;

public class SpringSecurityUserService implements UserDetailsService {

        private static Map<String, SysUser> db = new HashMap<String, SysUser>();

        static {

            BCryptPasswordEncoder bcr = new BCryptPasswordEncoder();

            SysUser sysUser1 = new SysUser();
            sysUser1.setUsername("admin");
            sysUser1.setPassword(bcr.encode("1234"));

            Permission permission1 = new Permission();
            permission1.setName("添加");
            permission1.setKeyword("add");

            Permission permission2 = new Permission();
            permission2.setName("修改");
            permission2.setKeyword("update");

            Role role1 = new Role();
            role1.setName("管理员");
            role1.setKeyword("ROLE_ADMIN");
            role1.getPermissions().add(permission1);
            role1.getPermissions().add(permission2);

            sysUser1.getRoles().add(role1);
            //到这为止  admin 就变成了 管理员角色 而且有了 add添加 和 update修改 俩权限




            SysUser sysUser2 = new SysUser();
            sysUser2.setUsername("zhangsan");
            sysUser2.setPassword(bcr.encode("1234"));

            Role role2 = new Role();
            role2.setName("普通用户");
            role2.setKeyword("ROLE_USER");

            Permission permission3 = new Permission();
            permission3.setName("删除");
            permission3.setKeyword("delete");

            Permission permission4 = new Permission();
            permission4.setName("查询");
            permission4.setKeyword("select");

            role2.getPermissions().add(permission3);
            role2.getPermissions().add(permission4);

            //给sysUser2 设置普通用户的角色 并且添加了查询select 和删除delete权限
            sysUser2.getRoles().add(role2);

            db.put(sysUser1.getUsername(),sysUser1);
            db.put(sysUser2.getUsername(),sysUser2);

        }




    /**
     *   loadUserByUsername 根据用户姓名加载用户 的意思
     * @param username  页面输入的用户名
     *
     * 这个方法的主要作用是：
     *        页面在登录时输入了用户名 而UserDetailsService会把这个值给拿过来 放在这个方法的参数里
     *        而我们要做的事情 就是根据这个用户名 去数据库查询他所对应的用户信息 比如用户名，密码，权限 这些内容
     *        查询出来之后 封装成UserDetails 返回给安全框架 安全框架获得咱们根据他给的用户名找出来的用户信息
     *        来判断 页面中输入的密码是否正确 有哪些权限   这些判断咱们是不需要管的 我们只需要根据他传过来的名字
     *        来找数据库中对应的用户信息就行了
     *
     *        这个实现类需要配置到spring-security.xml里面 有个叫认证提供者的地方 配置进去
     *        为什么叫认证提供者呢 因为这个实现类来根据传过来的用户名找到用户信息 然后提供给安全框架
     *        供他来判断
     *
     * @return
     * @throws UsernameNotFoundException
     */
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        SysUser sysUser = db.get(username);

        if (sysUser!=null){

            List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();

            //角色和权限 对于安全框架来讲 没有太大区别 都视为权限 所以都放到SimpleGrantedAuthority里面 一起返回就ok了
            //但是对于数据库 该区分还是正常区分的
            for (Role role : sysUser.getRoles()) {
                SimpleGrantedAuthority sga1 = new SimpleGrantedAuthority(role.getKeyword());
                list.add(sga1);
                for (Permission permission : role.getPermissions()) {
                    SimpleGrantedAuthority sga2 = new SimpleGrantedAuthority(permission.getKeyword());
                    list.add(sga2);
                }
            }

            UserDetails user = new User(sysUser.getUsername(),sysUser.getPassword(),list);

            return user;

        }


        return null;
    }


}
